grammar MediaWiki;
  
//class DokuWikiParser extends Parser;

options {
  output = AST;
}

@header {
    package agh.tk.markuptranslation;
}
@lexer::header {package agh.tk.markuptranslation;}

start returns [DataModel value] :
  node=mediaWikiFile
    { $value = $node.value; }
  ;

mediaWikiFile returns [DataModel value] :
	node1=mediaWikiMarkupSection node2=mediaWikiFile //Zmiana w 1 produkcji dodano Text
		{ $value = new DataModel($node1.value, (IComponent)$node2.value) ; }
	| node3=textBlock node4=mediaWikiFile 
		{ $value = new DataModel(new Text($node3.text, null), (IComponent)$node4.value) ; }
	| NEWLINE node5=mediaWikiFile 
		{ $value = new DataModel(new Text("\n", null), (IComponent)$node5.value) ; }
	| () 
		{ $value = null ; } ;

mediaWikiMarkupSection returns [IComponent value]:
	(
	node1=php
	{
	 $value=$node1.value ;
	} 
	| node2=markupSection
	{
	 $value=$node2.value ;
	} 
	| node3=list 
  {
   $value=$node3.value ;
  } 
	| node4=footnoteText 
  {
   $value=$node4.value ;
  } 
  | node123=boldAndItalicText
  {
    $value=$node123.value;
  }
	| node5=noCache 
  {
   //$value=$node5.value ;
  } 
	| node6=noToc 
  {
   //$value=$node6.value ;
  } 
	| node7=html 
  {
   $value=$node7.value ;
  } 
	| node8=codeBlock 
  {
   $value=$node8.value ;
  } 
	| node9=table 
  {
   $value=$node9.value ;
  } 
	| node10=qouting 
  {
   $value=$node10.value ;
  } 
	| node11=boldText 
  {
   $value=$node11.value ;
  } 
	| node12=italicText 
  {
   $value=$node12.value ;
  } 
	| node13=underlineText 
  {
   $value=$node13.value ;
  } 
	| newLine 
  {
   $value = new Text("\n", null) ;
  } 
	| node15=link
	{
	 $value = $node15.value ;
	}
	| node16=mail 
  {
   $value=$node16.value ;
  } 
	| node17=headline 
  {
   $value=$node17.value ;
  } 
	| node18=image 
  {
   $value=$node18.value ;
  } 
	| node19=noWiki
	{
   $value=$node19.value ;
  } 
	| node=horizontalRule
    { $value = $node.value; }
	)  ;

horizontalRule returns [IComponent value] :
  HORIZONTALRULE
    { $value = new Separator(SeparatorType.NORMAL); }
  ;

insideBoldText returns [Text value] :
  i=italicText in=insideBoldText 
  {
    $value = new Text($i.value, $in.value, null) ;
  }
  | u=underlineText in2=insideBoldText
  {
    $value = new Text($u.value, $in2.value, null) ;
  }
  | l=line in3=insideBoldText
  {
    $value = new Text(new Text($line.text, null), $in3.value, null) ;
  }
  | NEWLINE in4=insideBoldText
  {
    $value = new Text(new Text("\n", null), $in4.value, null) ;
  }
  | ()
  {
    $value = null ;
  };
	
boldText returns [Text value] :
	BOLDSYMBOL i=insideBoldText BOLDSYMBOL 
		{
		  $i.value.setTextFormatting(TextFormatting.BOLD) ;
  	 $value = $i.value ;
		};

insideItalicText returns [Text value] :
  b=boldText i1=insideItalicText
  {
    $value = new Text($b.value, $i1.value, null) ;
  }
  | u=underlineText i2=insideItalicText
  {
    $value = new Text($u.value, $i2.value, null) ;
  }
  | l=line i3=insideItalicText
  {
    $value = new Text(new Text($l.text, null), $i3.value, null) ;
  }
 | NEWLINE in4=insideItalicText
  {
    $value = new Text(new Text("\n", null), $in4.value, null) ;
  }
  | ()
  {
    $value = null ;
  } ;
		
italicText returns [Text value] :
	ITALICSYMBOL i=insideItalicText ITALICSYMBOL 
		{ 
      $i.value.setTextFormatting(TextFormatting.ITALIC) ;
		  $value = $i.value ;
	  };

insideBoldAndItalicText returns [Text value] :
  u=underlineText i2=insideBoldAndItalicText
  {
    $value = new Text($u.value, $i2.value, null) ;
  }
  | l=line i3=insideBoldAndItalicText
  {
    $value = new Text(new Text($l.text, null), $i3.value, null) ;
  }
 | NEWLINE in4=insideBoldAndItalicText
  {
    $value = new Text(new Text("\n", null), $in4.value, null) ;
  }
  | ()
  {
    $value = null ;
  } ;
	  
boldAndItalicText returns [Text value] :
  BOLDANDITALIC t=insideBoldAndItalicText BOLDANDITALIC
    {
      $t.value.setTextFormatting(TextFormatting.ITALIC);
      $value = new Text($t.value, null, TextFormatting.BOLD); 
    };

deletedText returns [Text value] :
	DELETED node=text DELETEDC
	{
		$value = new Text($node.value.toString(), null) ;	
	};

insideUnderlineText returns [Text value] :
  b=boldText i1=insideUnderlineText
  {
    $value = new Text($b.value, $i1.value, null) ;
  }
  | i=italicText i2=insideUnderlineText
  {
    $value = new Text($i.value, $i2.value, null) ;
  }
  | l=line i3=insideUnderlineText
  {
    $value = new Text(new Text($l.text, null), $i3.value, null) ;
  }
 | NEWLINE in4=insideUnderlineText
  {
    $value = new Text(new Text("\n", null), $in4.value, null) ;
  }
  | ()
  {
    $value = null ;
  } ;
	
underlineText returns [Text value] :
	UNDERLINESYMBOL i=insideUnderlineText UNDERLINESYMBOL
		{
		  $i.value.setTextFormatting(TextFormatting.UNDERLINE) ;
		  $value = $i.value ; 
		};

footnoteText returns [Text value]:
	FOOTNOTESYMBOL node=text FOOTNOTESYMBOLC
		{ $value = new Text($node.value.toString(), TextFormatting.FOOTNOTE) ; };

text returns [Text value] :
	t1=textBlock t2=text 
		{ $value = new Text($t1.text + $t2.value.toString(), null) ;}  
	| NEWLINE t=text
		{ $value = new Text("\n" + $t.value.toString(), null) ;}  
	|	()
		{ $value = new Text("", null) ; } ;

newLine :
	NEWLINESYMBOL ;
	
link returns [Link value] :
	(LINKSYMBOL (a=ADDRESS | p=linkText) (LINKTEXTSYMBOL t=text)? LINKSYMBOLC)
		{
			if($a != null) //CZY $a.value
				if($t.value != null) 
					$value = new Link(new Text($a.text, null), new Text($t.value.toString(), null)) ; 
				else
					$value = new Link(new Text($a.text, null), null) ;
			if($p.value != null)//p.value auch nicht null?
				if( $t.value != null) 
					$value = new Link(new Text($p.value.toString(), null), new Text($t.value.toString(), null)) ; 
				else
					$value = new Link(new Text($p.value.toString(), null), null) ;
		}
	| a1=ADDRESS 
		{ $value = new Link(new Text($a1.text, null), null) ; };

mail returns [Mail value] : 
	m=MAIL
		{ $value = new Mail(new Text($m.text.substring(1, $m.text.length() - 1), null), null) ; }  ;
	
linkText returns [Text value] : 
	t1=textBlock t2=linkText
	{
		String t2Text = "" ;
		if($t2.value != null) //CZY $t2.value
			t2Text = $t2.value.toString() ;
		$value = new Text($t1.text + t2Text, null) ;
	} 
	| () 
	{
		$value = null ;
	};

headline returns [Headline value] :
	h1=HEADLINESYMBOL t=text h2=HEADLINESYMBOL 
	{
		if($h1.text.length() == $h2.text.length())
      $value = new Headline($t.value.toString(), $h1.text.length()-1) ;
    else 
    {
      if($h1.text.length() > $h2.text.length())
        $value = new Headline($h1.text.substring( $h2.text.length()) + $t.value.toString(), $h2.text.length()-1) ;
      else
        $value = new Headline($t.value.toString() + $h2.text.substring( $h1.text.length()), $h1.text.length()-1) ;
        
    }
	};

textBlock :
	(WHITESPACE | WORD | PUNCTUATIONMARK | NUMBER | SPECIALPUNCTUATIONMARK); 

image returns [Image value] : 
	IMAGESYMBOL (p=linkText | a=ADDRESS) (s=SIZE)? (LINKTEXTSYMBOL t=text)? IMAGESYMBOLC
	{
		IComponent left = null ;
		String addressString = null ;
		if($s.text != null)
		{
			String[] sizeTable = $s.text.substring(1).split("x") ;
			String x = sizeTable[0] ;
			String y = null ;
			if(sizeTable.length > 1) 
				y = sizeTable[1] ;
			if($p.value != null)
				left = new ResizableImage(new Text($p.value.toString(),null), new Size(x, y)) ;
			else
				left = new ResizableImage(new Text($a.text, null), new Size(x, y)) ;
		}
		else
		{	
		  int lastIndex = -1 ;	
		  if(a != null)
  		  lastIndex = $a.text.lastIndexOf("?") ;
		  Size size2 = null ;
		  if(lastIndex > 0)
		  {
  		  String size = $a.text.substring(lastIndex + 1) ;
  		  if(size.matches("\\d+x?\\d*"))
  		  {
  		    addressString = $a.text.substring(0, lastIndex) ;
  		    String[] sizeTable = size.split("x") ;
          String x = sizeTable[0] ;
          String y = null ;
          if(sizeTable.length > 1) 
            y = sizeTable[1] ;
          size2 = new Size(x, y) ;
  		  }
		  }
		  if(size2 == null)
		  {
				if($p.value != null)
					left = new Text($p.value.toString(), null) ;
				else
					left = new Text($a.text, null) ;
			}
			else
			{
	        left = new ResizableImage(new Text(addressString, null), size2) ;
			}
		}
		if($t.value != null)
			$value = new Image(left, new Text($t.value.toString(), null)) ;		
		else
			$value = new Image(left, null) ;		
	} ;

list returns [AbstractWikiList value] : 
	l=LISTSYMBOL li=line (NEWLINE | lis=list)
	{
	  IComponent nextListItem ;
	  IComponent text = null ;
	  if(!$li.text.equals(""))
	     text = new Text($li.text, null) ;
	  if($lis.value == null)
      nextListItem = new Text("\n", null) ;
    else
      nextListItem = $lis.value ;
		if($l.text.endsWith("*"))
			$value = new UnorderedList(new Text($li.text, null), nextListItem ) ;
		else
			$value = new OrderedList(text, nextListItem) ;
		int level = $l.text.length() / 2;
		((AbstractWikiList)$value).setLevel(level) ;
	} ;

qouting returns [Quote value] :
	(q=QUOTINGSYMBOL) (l=line)
	{
		$value = new Quote($l.text, $q.text.length() - 3) ;
	} ;

table returns [Table value] :
	HEADERTABLESYMBOL head=tableHeader row=tableRows
	{
		$value = new Table((IComponent)$head.value, (IComponent)$row.value) ;
	};

tableHeader returns [TableHeader value] :
	t=linkText HEADERTABLESYMBOL h=tableHeader 
	{
		$value = new TableHeader(new Text($t.value.toString(), null), (IComponent)$h.value) ;
	}
	| NEWLINE
	{
		$value = null ;
	}
	 ;

tableRows returns [Table value]:
	LINKTEXTSYMBOL row=tableRow next=tableRows
	{
		$value = new Table((IComponent)$row.value, (IComponent)$next.value) ;	
	}
	| () 
	{
		$value = null ;
	} ; 
	
tableRow returns [TableRow value] :
	l=linkText LINKTEXTSYMBOL t=tableRow
	{	
		if($l.value != null)
			$value = new TableRow(new Text($l.value.toString(), null), (IComponent)$t.value) ;
		else
			$value = new TableRow(null, (IComponent)$t.value) ;
			
	}
	| NEWLINE
	{
		$value = null ;
	};
		
noWiki returns [NoWikiBlock value] :
	NOWIKI t=mediaWikiFile NOWIKIC 
	{
		$value = new NoWikiBlock($t.value.toDokuWiki()) ; ;	
	}
	| NOWIKI2 a=allWithoutNowiki2 NOWIKI2 
	{
	 $value = new NoWikiBlock($a.text) ;
	};

allWithoutNowiki2 :
  (~NOWIKI2)* ;
	
codeBlock returns [IComponent value] :
	c=CODE t=mediaWikiFile CODEC
	{
		$value = new CodeBlock(((IComponent)$t.value).toDokuWiki()) ;
		if($c.text.length() > 6)
		{
			String language = $c.text.substring($c.text.indexOf(' ') + 1, $c.text.length() -1) ;
			((CodeBlock)$value).setLanguage(language) ;
		}
	}
	| f=FILE s=mediaWikiFile FILEC
	{
		$value = new CodeBlock(((IComponent)$s.value).toDokuWiki()) ;
		if($f.text.length() > 6)
		{
			String language = $f.text.substring($f.text.indexOf(' ') + 1, $f.text.length() -1) ;
			((CodeBlock)$value).setLanguage(language) ;
		}
	}
	| c=CODESECTION u=linkText NEWLINE
	{
	  if($u.value == null)
	     $value = new Text($c.text + "\n", null) ;
	  else
  		$value = new Text($u.value.toString(), TextFormatting.VERBATIMLINE) ;
	} ;
	
html returns [HTMLSection value] :
	HTML b=allWithoutHtmlc HTMLC
	{
		$value  = new HTMLSection($b.text) ;
	} 
	| HTML2 a=allWithoutHtml2C HTML2C
	{
    $value = new HTMLSection($a.text) ;
	};

allWithoutHtmlc :
  (~HTMLC)* ;

allWithoutHtml2C :
  (~HTML2C)* ;
	
php returns [PHPSection value] :
	PHP d=allWithoutPhpc PHPC
	{
		$value = new PHPSection($d.text) ;	
	}
	| PHP2 a=allWithoutPhp2c PHP2C
	{
    $value = new PHPSection($a.text) ;
	};	

allWithoutPhpc :
  (~PHPC)* ;

allWithoutPhp2c :
  (~PHP2C)* ;
	
markupSection returns [Text value] :
	m=MARKUP
	{
		$value = new Text($m.text, null) ;
	} ;
	
line :
  (textBlock)+ ;
	
noCache returns [IComponent value]:
	NOCACHE { $value = null;};

noToc returns [IComponent value]:
	NOTOC { $value = null;};
	
//LEXER
//options 
//{
//  k = 10 ;
  //filter = true ;
  //caseSensitive = false ;
//}

BOLDANDITALIC:
  '\'\'\'\'\'' ;
  
PREFORMATTED:
  '\'\'\'\'' ;

BOLDSYMBOL : 
  '\'\'\'' ;
  
ITALICSYMBOL :
  '\'\'' ;
  
UNDERLINESYMBOL :
  '__' ;

DELETED :
  '<del>' ;

DELETEDC :
  '</del>' ;
  
SUBSCRIPT :
  '<sub>' ;

SUBSCRIPTC :
  '</sub>' ;

SUPERSCRIPT :
  '<sup>' ;

SUPERSCRIPTC :
  '</sup>' ;
  
NEWLINESYMBOL :
  '\\\\' WHITESPACE ;
  
HEADERTABLESYMBOL :
  '^' ;
    
IMAGESYMBOL :
  '{{' ;
  
IMAGESYMBOLC :
  '}}' ;
    
ADDRESS :
  ('www.' | 'http://') WORD ('.' WORD)+ ('/' (LETTER | DIGIT | PUNCTUATIONMARK)+)? ;
  
LINKSYMBOL :
  '[[' ;

LINKSYMBOLC : 
  ']]' ;
  
fragment LISTSYMBOL :
  NEWLINE ('*'+ | '#'+) ; 

NEWLINE_OR_CODESECTION :
  NEWLINE
  (
    ('>')+ ' '
    {
      $type = QUOTINGSYMBOL ;
    }
    | ('*'+ | '#'+) 
    {
      $type = LISTSYMBOL ;
    }
    |( (' ')+
    (
	    ()
	    {
	      if($text.length() > 2)
	        $type = CODESECTION ;
	      else
	        $type = NEWLINE ;
	    })
    )
    | ()
     {
      $type = NEWLINE ;
     }
  ) ;

fragment CODESECTION :
  NEWLINE ('  ') (' ')* ;

FOOTNOTESYMBOL :
  '((' ;

FOOTNOTESYMBOLC :
  '))' ;
  
fragment QUOTINGSYMBOL :
  NEWLINE ('>')+ ' ' ;  

HEADLINESYMBOL :
  '=' ('=')+ ;

//HEADLINEEND :
//  ('=' ('=')+) ;
NUMBER :
  (DIGIT)+ ;
  
SIZE :
  '?' 
  (
    (NUMBER ('x' NUMBER)?)
    {
      $type = SIZE;
    }
    | ()
    {
      $type = PUNCTUATIONMARK ;
    }
  ) ;
  
REVERSE :
  'reverse' ;

AUTHOR :
  'author' ;
  
DATE :
  'date' ;

DESCRIPTION :
  'description' ;

WORD :
  (LETTER | DIGIT)+ ;

NOWIKI :
  '<nowiki>' ;
  
NOWIKIC :
  '</nowiki>' ;
  
CODE :
  '<code' (' ' (LETTER | DIGIT | '_' | '#' | '-')*)? '>' ;
  
CODEC :
  '</code>' ;

FILE :
  '<file' (' ' (LETTER | DIGIT | '_' | '#' | '-')*)? '>'  ;

FILEC :
  '</file>'  ;
  
HORIZONTALRULE : 
  '----';
  
HTML :
  '<html>' ;
  
HTMLC :
  '</html>' ;

HTML2 :
  '<HTML>' ;

HTML2C :
  '</HTML>' ;
  
PHP :
  '<php>' ;

PHPC :
  '</php>' ;

PHP2 :
  '<PHP>' ;

PHP2C :
  '</PHP>' ;

MAIL :
  '<' (WORD) ('.' WORD)* '@' WORD ('.' WORD)+ '>' ;
  
MARKUP :
  '<' ('/')? WORD (LETTER | DIGIT | PUNCTUATIONMARK | WHITESPACE)* '>' ;
  
PUNCTUATIONMARK :
  '~' | ']' | '\\' | '[' |'$' | '_' | '%' | '(' | ')' | ',' | '?' | ';' | '!' | '"' | '-' | '/' | ':' | '='  | '.' | '#' | '<' | '@' | '\'' | '*' | '{' ;

SPECIALPUNCTUATIONMARK :
  '}' | '>' ;
  
NOWIKI2 :
  '%%' ;

LINKTEXTSYMBOL :
  '|' ;
  
fragment LETTER :
  'a'..'z'|'A'..'Z' ;
  
fragment DIGIT :
  '0'..'9' ;

WHITESPACE :
    ' '
    | '\t'
    | '\f' ;
  
fragment NEWLINE :
  ( '\r\n' 
  | '\n'
  ) ;  
